﻿using System;
using Moq;
using NUnit.Framework;
using Dominio.Entidades;
namespace Dominio_Test.UnitTest
{
    [TestFixture]
    public class CalculoTest
    {
        #region ctor

        [Test]
        public void ctor_PrimerOperandoEsNull_ThrwoArgumentNullException()
        {
            //ARRANGE

            IOperando primerOperando = null;

            //ACT and ASSERT
            Assert.Throws<ArgumentNullException>(() => new Calculo(primerOperando, Mock.Of<IOperando>()));

        }

        [Test]
        public void ctor_SegundoOperandoIsNUll_ThrowArgumenNullException()
        {
            //ARRANGE

            IOperando segundoOperando = null;


            //ACT and ASSERT
            Assert.Throws<ArgumentNullException>(() => new Calculo(Mock.Of<IOperando>(), segundoOperando));
        }

        #endregion

        #region calcular

        [Test]
        public void calcular_EstrategiaEsNull_ThroArgumentNullException()
        {
            //ARRANGE
            var calculo = newCalculo();
            IOperadorStrategy operadorStrategy = null;

            //ACT and ASSERT

            Assert.Throws<ArgumentNullException>(() => calculo.calcular(operadorStrategy));
            
        }

        [Test]
        public void calcular_OperadorStrategyIsNotNull_VerifyDefaultResultado()
        {
            //ARRANGE

            var calculo = newCalculo();
            var estrategia = newStrategiaMock();
            Mock.Get(estrategia).Setup(c => c.resultadoPorDefecto(Resultado.cero)).Returns(estrategia);

            //ACT
            calculo.calcular(estrategia);


            //ASSERT
            Mock.Get(estrategia).Verify(c => c.resultadoPorDefecto(Resultado.cero));
        }

        [Test]
        public void calcular_AsignadoElResultadoPorDefecto_VerficarCalcularResultado()
        {
            //ARRANGE

            var calculo = newCalculo();
            var estrategia = newStrategiaMock();

            Mock.Get(estrategia).Setup(c => c.resultadoPorDefecto(Resultado.cero)).Returns(estrategia);

            //ACT
            calculo.calcular(estrategia);
            

            //ASSERT
            Mock.Get(estrategia).Verify(c => c.calcularResultado(calculo));
        }

        #endregion


        #region auxiliares

        private IOperadorStrategy newStrategiaMock()
        {
            var assemble = typeof (Mock).Assembly;
            return Mock.Of<IOperadorStrategy>();
        }


        private Calculo newCalculo()
        {
            

            return new Calculo(newPrimerOperando(),newSegundoOperador());
        }

        private IOperando newSegundoOperador()
        {
            return Mock.Of<IOperando>();
        }

        private IOperando newPrimerOperando()
        {
            return Mock.Of<IOperando>();
        }

        #endregion

    }
}

